package sil

/**
 * Clase inmutable que define una palabra como la palabra propiamente dicha, 
 * una colección de las sílabas que la componen, cuál es la tónica y cuáles son
 * sus rimas asonante y consonante.
 * @author Jorge Tercero
 */
class Palabra
{
  public final static int AGUDA=1;
  public final static int LLANA=2;
  public final static int ESDRUJULA=3;
  public final static int SOBREESDRUJULA=4;

  public final vocales = /a|e|i|o|u|á|é|í|ó|ú/;

  /**
   * Sustituye una vocal por ella misma con tilde a->á á->á
   */
  def conTilde(vocal) {
    switch(vocal) {
      case 'a': return 'á'
      case 'á': return 'á'
      case 'e': return 'é'
      case 'é': return 'é'
      case 'i': return 'í'
      case 'í': return 'í'
      case 'o': return 'ó'
      case 'ó': return 'ó'
      case 'u': return 'ú'
      case 'ú': return 'ú'
    }
  }
  
  Silabeador silabeador
  String palabra
  String[] silabas
  int tonica
  int acento

  /**
   * Construye una instancia de <code>Palabra</code> a partir de <code>palabra</code>
   * @param palabra String representando una palabra.
   */
  Palabra(palabra)
  {
    if (palabra == null || palabra.length()==0) throw new Exception("debes pasar como param una palabra")
    silabeador = new Silabeador();
    this.palabra = palabra
    silabas = silabeador.silabear(palabra)
    tonica = silabeador.tonica(this.silabas)
    acento = silabas.size() - tonica
    if (acento>4) acento = 4    
  }

  /**
   * Devuelve la rima consonante de la palabra.
   * De la <a href="http://es.wikipedia.org/wiki/Rima_consonante">wikipedia</a>: se dice que riman 
   * consonantemente las palabras en las que coinciden todos los sonidos a partir de la última vocal tónica.
   */
  def consonante()
  {
    def silabaTonica = silabas[tonica]
    // posición de la vocal tónica dentro de la sílaba tónica
    def vTonica = silabeador.vocalTonica(silabaTonica)
    def charSilabaTonica = silabaTonica.toLowerCase().toCharArray()
    
    // reemplazamos la vocal tónica por ella misma acentuada a -> á
    charSilabaTonica[vTonica] = conTilde(charSilabaTonica[vTonica])
    
    // tomamos las letras de la sílaba tónica que están después de la vocal tónica: miel -> el; mas -> as
    def consonante = (charSilabaTonica[vTonica..charSilabaTonica.size()-1]).join()

    // si la palabra tiene sílabas después de la tónica las anexamos al final
    if (silabas.size()>tonica+1) consonante += silabas[tonica+1..silabas.size()-1].join()
    return consonante
  }
  
  /**
   * Devuelve la rima asonante de la palabra.
   * De la <a href="http://es.wikipedia.org/wiki/Rima_asonante">wikipedia</a>:
   * Se dice que riman de forma asonante las palabras en las que coinciden las vocales acentuadas de cada sílaba a partir de
   * la última vocal tónica. Esto excluye las vocales no acentuadas de los diptongos, por lo que "calma" rima asonantemente con
   * "ardua", y "rey" con "fe". Además, la "u" postónica se considera equivalente a la "o", y la "i" equivalente a la "e": así
   * "Venus" rima con "cielo". En las palabras esdrújulas, sólo se toman en cuenta la vocal tónica y la de la sílaba final: por
   * tanto, "súbito" rima con "turco" en ú-o.
   */
  def asonante()
  {
    def rima = [], ret = []
    def silabaTonica = silabas[tonica]
    // posición de la vocal tónica dentro de la sílaba tónica
    def vTonica = silabeador.vocalTonica(silabaTonica)
    def charSilabaTonica = silabaTonica.toLowerCase().toCharArray()

    // reemplazamos la vocal tónica por ella misma acentuada a -> á
    rima << conTilde(charSilabaTonica[vTonica])
    
    if (silabas.size()>tonica+1) rima += silabas[tonica+1..silabas.size()-1]
    rima.each { ret << it[silabeador.vocalTonica(it)] }
    ret = vocalesEquivalentes(ret)
    ret = esdrujulas(ret)
    return ret.join()
  }
  
  /**
   * Vocales equivalentes en rima asonante.
   * <p>
   * (...) Además, la "u" postónica se considera equivalente a la "o", y la "i" equivalente a la "e" (...)
   * Reemplaza las e-o por i-u, si la vocal lleva tilde la deja como está, pues es la tónica de la rima.
   */
  def vocalesEquivalentes(vocales)
  {
    def ret = []
    vocales.each {
      if (it=='e') ret << 'i'
      else if (it=='o') ret << 'u'
      else ret << it
    }
    return ret
  }

  /**
   * Devuelve las vocales relevantes en palabras esdrújulas.
   * <p>
   * En rima asonante:
   * (...) En las palabras esdrújulas, sólo se toman en cuenta la vocal tónica y la de la sílaba final (...)
   * Si el array tiene tres elementos, devuelve un nuevo array con los elementos [0,2]
   */
  def esdrujulas(vocales)
  {
    if (vocales.size()==3) return [vocales[0], vocales[2]]
    return vocales
  }
  
  def String toString()
  {
    return palabra
  }
}

